#!/usr/local/ey_resin/ruby/bin/ruby

require 'rubygems'
require 'aws/s3'
require 'date'
require 'digest'
require 'net/http'
require 'fileutils'
require 'json'

module AWS::S3
  class S3Object
    def <=>(other)
      DateTime.parse(self.about['last-modified']) <=> DateTime.parse(other.about['last-modified'])
    end
  end
end

AWS::S3::Base.establish_connection!(
  :access_key_id     => '<%= @id_key %>',
  :secret_access_key => '<%= @secret_key %>'
)

@databases = JSON.parse(`mongo --quiet --eval "printjson(db.runCommand('listDatabases').databases)" admin`)
@databases.map! { |db| db["sizeOnDisk"] >= 1 ? db["name"] : nil }.compact!

@ismaster = `mongo --quiet --eval 'printjson(db.runCommand("ismaster"))' | grep ismaster | awk '{print $3}'| sed s/,//`.strip
@environment = '<%= @env %>'
@app_name = '<%= @app_name %>'
@keep = 10 * @databases.length
@bucket = "ey-backup-#{Digest::SHA1.hexdigest('<%= @id_key %>')[0..11]}-mongo"
@tmpname = "#{Time.now.strftime("%Y-%m-%dT%H:%M:%S").gsub(/:/, '-')}"
FileUtils.mkdir_p '/mnt/tmp'
begin
  AWS::S3::Bucket.create @bucket
rescue AWS::S3::BucketAlreadyExists
end

if @ismaster == "false" #only dump non-primary nodes
  @databases.each do |database|
    token = "#{database}"
    mongocmd = "mongodump -h 127.0.0.1 -d #{database} -o /mnt/tmp/#{token}.#{@tmpname} && tar cjf \"/mnt/tmp/#{token}.#{@tmpname}.tar.bz\" \"/mnt/tmp/#{token}.#{@tmpname}\""
    if system(mongocmd)
      AWS::S3::S3Object.store(
        "/#{@environment}.#{@app_name}/#{@app_name}-#{token}.#{@tmpname}.bson.tar.bz",
        open("/mnt/tmp/#{token}.#{@tmpname}.tar.bz"),
        @bucket,
        :access => :private
      )
      FileUtils.rm "/mnt/tmp/#{token}.#{@tmpname}.tar.bz"
      FileUtils.rm_r "/mnt/tmp/#{token}.#{@tmpname}"
      puts "successful backup: #{database}.#{@tmpname}"
    else
      raise "Unable to dump database#{database}!"
    end
  end

  backups = []
  backups << AWS::S3::Bucket.objects(@bucket).sort
  backups = backups.flatten.sort
  backups[0...-@keep].each do |object|
    puts "deleting: #{object.key}"
    object.delete
  end
end
